﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace async
{
    class Program
    {
        //#region Task使用
        //static void Main(string[] args)
        //{
        //    Console.WriteLine("执行GetReturnResult方法前的时间：" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));

        //    //主线程并没有阻塞去执行GetReturnResult()方法，而是开启了另一个线程去执行GetReturnResult()方法。
        //    //直到执行strRes.Result这一句的时候主线程才会等待GetReturnResult()方法执行完毕
        //    //Task.Run<string>(()=>{}).Reslut是阻塞主线程的，因为主线程要得到返回值，必须要等方法执行完成。
        //    var strRes = Task.Run<string>(() => { return GetReturnResult(); });
        //    Console.WriteLine("执行GetReturnResult方法后的时间：" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
        //    Console.WriteLine("我是主线程，线程ID：" + Thread.CurrentThread.ManagedThreadId);
        //    Console.WriteLine(strRes.Result);
        //    Console.WriteLine("得到结果后的时间：" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));

        //    Console.ReadLine();
        //}

        //static string GetReturnResult()
        //{
        //    Console.WriteLine("我是GetReturnResult里面的线程，线程ID：" + Thread.CurrentThread.ManagedThreadId);
        //    Thread.Sleep(4000);
        //    return "我是返回值";
        //} 
        //#endregion

        //#region MyRegion
        ///// <summary>
        ///// (1)在async标识的方法体里面，如果没有await关键字的出现，那么这种方法和调用普通的方法没什么区别。
        ///// (2)在async标识的方法体里面，在await关键字出现之前，还是主线程顺序调用的，直到await关键字的出现才会出现线程阻塞。
        ///// (3)await关键字可以理解为等待方法执行完毕，除了可以标记有async关键字的方法外，还能标记Task对象，表示等待该线程执行完毕。所以await关键字并不是针对于async的方法，而是针对async方法所返回给我们的Task。
        ///// (4)异步方法的返回类型必须为void、Task或者Task<T>类型。也就是说async要么是void，要么和Task关联。
        ///// </summary>
        ///// <param name="args"></param>
        //static void Main(string[] args)
        //{
        //    Console.WriteLine("我是主线程，线程ID：{0}", Thread.CurrentThread.ManagedThreadId);
        //    TestAsync();
        //    Console.ReadLine();
        //}

        //static async Task TestAsync()
        //{
        //    Console.WriteLine("调用GetReturnResult()之前，线程ID：{0}。当前时间：{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
        //    var name = GetReturnResult();
        //    Console.WriteLine("调用GetReturnResult()之后，线程ID：{0}。当前时间：{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
        //    Console.WriteLine("得到GetReturnResult()方法的结果：{0}。当前时间：{1}", await name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
        //}

        //static async Task<string> GetReturnResult()
        //{
        //    Console.WriteLine("执行Task.Run之前, 线程ID：{0}", Thread.CurrentThread.ManagedThreadId);
        //    return await Task.Run(() =>
        //    {
        //        Thread.Sleep(3000);
        //        Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
        //        return "我是返回值";
        //    });
        //} 
        //#endregion

        static void Main(string[] args)
        {
            var result = MyMethod(); //将异步执行

            //Console.WriteLine("end");

            Console.WriteLine(result.Result); //比方法1多了一行

            Console.WriteLine("end");

            Console.ReadLine();
        }

        static async Task<int> MyMethod()
        {
            for (int i = 0; i < 15; i++)
            {
                await Task.Delay(1000); //模拟耗时操作

                Console.WriteLine("异步执行" + i.ToString() + "..");
            }
            return 0;
        }
    }
}
